/*
 * Tank.cpp
 *
 *  Created on: 04.10.2013
 *      Author: dima
 */


#include "../Globals.hpp"
#include "TankModel.hpp"

#include <string>


Tanks::
Model::
TankModel::
TankModel() :
  m_alive(true),
  m_moving(false),
  m_shooting(false),
  m_exploding(false),
  m_damage(0),
  m_fireRate(0.0),
  m_missileSpeed(0),
  m_speed(0),
  m_health(0),
  m_oldX(0),
  m_oldY(0),
  m_lastShot(-1),
  m_XVelocity(0),
  m_YVelocity(0),
  m_direction(DirectionDown),
  m_explosionStartTime(-1),
  m_explosionDuration(32)
{
  CollisionModel & collisionModel = CollisionModel::getInstance();
  collisionModel.RegisterObject(this);
}


Tanks::
Model::
TankModel::
~TankModel()
{}


void
Tanks::
Model::
TankModel::
Tick()
{
  ++m_ticks;

  if(!m_alive)
  {
    return;
  }

  if(m_lastShot < m_ticks - 1)
  {
    m_shooting = false;
  }
  if(m_exploding)
  {
    if(m_ticks - m_explosionStartTime >= m_explosionDuration)
    {
      CollisionModel & collisionModel = CollisionModel::getInstance();
      collisionModel.RemoveObject(this);
      m_alive = false;
      m_exploding = false;
    }
    return;
  }

  m_rect->x += m_XVelocity * m_speed;
  m_rect->y += m_YVelocity * m_speed;

  if(m_rect->x < 0) m_rect->x = 0;
  if(m_rect->y < 0) m_rect->y = 0;
  if(m_rect->x + m_rect->w > 1024) m_rect->x = Globals::screenWidth - m_rect->w;
  if(m_rect->y + m_rect->h > 768)  m_rect->y = Globals::screenHeight  - m_rect->h;

  std::map<unsigned int, MissileModel *>::iterator missileIter;

  CollisionModel & collisionModel = CollisionModel::getInstance();
  collisionModel.CheckCollision(this);

  if(m_rect->x != m_oldX || m_rect->y != m_oldY)
  {
    m_moving = true;
  }
  else
  {
    m_moving = false;
  }
  m_oldX = m_rect->x;
  m_oldY = m_rect->y;
}


void
Tanks::
Model::
TankModel::
Collision(Tanks::Model::GameObjectModel * argGameObjectModel,
      Tanks::Model::CollisionModel::CollisionSide argCollisionSide,
      bool argActive)
{
  if(argActive &&
   ((argGameObjectModel->GetType() == SolidBlock) ||
    (argGameObjectModel->GetType() >= Player && argGameObjectModel->GetType() <= TankHard)))
  {
    if(m_direction == DirectionLeft)
    {
      m_rect->x = argGameObjectModel->GetRect()->x + argGameObjectModel->GetRect()->w + 1;
    }
    if(m_direction == DirectionUp)
    {
      m_rect->y = argGameObjectModel->GetRect()->y + argGameObjectModel->GetRect()->h + 1;
    }
    if(m_direction == DirectionRight)
    {
      m_rect->x = argGameObjectModel->GetRect()->x - m_rect->w - 1;
    }
    if(m_direction == DirectionDown)
    {
      m_rect->y = argGameObjectModel->GetRect()->y - m_rect->h - 1;
    }
  }

  if(argGameObjectModel->GetType() == Missile &&
     argGameObjectModel->GetTeam() != m_team &&
     !argActive)
  {
    m_health -= 100;
    if(m_health <= 0)
    {
      Die();
    }
  }
}


void
Tanks::
Model::
TankModel::
Shoot()
{
  if(m_exploding || !m_alive)
  {
    return;
  }
  float timeSinceLastShot = (m_ticks - m_lastShot) * (1.0/(float)Globals::FPS);
  if(timeSinceLastShot < m_fireRate)
  {
    return;
  }
  int midX, midY;
  midX = m_rect->x + (int)(m_rect->w/2) - 5;
  midY = m_rect->y + (int)(m_rect->h/2) - 5;

  MissileModel * missile = NULL;
  if(m_direction == DirectionLeft)
  {
    missile = new MissileModel(m_rect->x - 10, midY, m_team, this);
  }
  if(m_direction == DirectionUp)
  {
    missile = new MissileModel(midX, m_rect->y - 10, m_team, this);
  }
  if(m_direction == DirectionRight)
  {
    missile = new MissileModel(m_rect->x + m_rect->w, midY, m_team, this);
  }
  if(m_direction == DirectionDown)
  {
    missile = new MissileModel(midX, m_rect->y + m_rect->h, m_team, this);
  }
  if(missile == NULL) return;

  missile->SetDirection(m_direction);
  m_lastShot = m_ticks;
  m_shooting = true;
}





void
Tanks::
Model::
TankModel::
Die()
{
  if(m_explosionStartTime > -1) return;

  m_exploding = true;
  SetVelocity(0, 0);

  if(m_explosionStartTime == -1)
  {
    m_explosionStartTime = m_ticks;
  }
}


void
Tanks::
Model::
TankModel::
SetVelocity(int argXVelocity, int argYVelocity)
{
  if(m_explosionStartTime > -1)
  {
    return;
  }

  m_XVelocity = argXVelocity;
  m_YVelocity = argYVelocity;
  if(m_XVelocity == 0 && m_YVelocity == 0)
  {
    m_moving = false;
  }
  else if(m_XVelocity > 0 && m_YVelocity == 0)
  {
    m_direction = DirectionRight;
  }
  else if(m_XVelocity < 0 && m_YVelocity == 0)
  {
    m_direction = DirectionLeft;
  }
  else if(m_XVelocity == 0 && m_YVelocity > 0)
  {
    m_direction = DirectionDown;
  }
  else if(m_XVelocity == 0 && m_YVelocity < 0)
  {
    m_direction = DirectionUp;
  }
  else
  {
    throw std::string("SetVelocity in TankModel: The tank is only able to move left, up, right and down.");
  }
}


